package com.example.networklab.mq.listener;

import com.example.networklab.constants.MQConstants;
import com.example.networklab.domain.po.Task;
import com.example.networklab.enums.TaskStatus;
import com.example.networklab.mq.dto.TaskStatusMQDTO;
import com.example.networklab.service.ITaskService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

@Component
@RequiredArgsConstructor
@Slf4j
public class TaskStatusChangeListener {
    private final ITaskService taskService;
    private static final int DEVIATION = 1;

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = MQConstants.DELAY_TASK_STATUS_QUEUE_NAME, durable = "true"),
            exchange = @Exchange(name = MQConstants.DELAY_EXCHANGE_NAME, delayed = "true"),
            key = MQConstants.DELAY_TASK_STATUS_KEY
    ))
    public void listenTaskStatusChange(TaskStatusMQDTO taskStatusMQDTO) {
        log.info("收到队列名为[{}]延时消息:[{}]", MQConstants.DELAY_TASK_STATUS_QUEUE_NAME, taskStatusMQDTO);
        LocalDateTime now = LocalDateTime.now();
        Task task = taskService.getById(taskStatusMQDTO.getId());
        if (task == null) {
            log.error("队列[{}]消息处理失败:[{}]", MQConstants.DELAY_TASK_STATUS_QUEUE_NAME, taskStatusMQDTO);
            return;
        }
        if (taskStatusMQDTO.getStatus() == TaskStatus.IN_PROGRESS) {
            if (deviationTime1BeforeTime2(now, task.getEndTime()) && deviationTime1AfterTime2(now, task.getStartTime())) {
                task.setStatus(TaskStatus.IN_PROGRESS);
                taskService.updateById(task);
            }
        } else if (taskStatusMQDTO.getStatus() == TaskStatus.END) {
            if (deviationTime1AfterTime2(now, task.getEndTime())) {
                task.setStatus(TaskStatus.END);
                taskService.updateById(task);
            }
        }
    }

    private boolean deviationTime1BeforeTime2(LocalDateTime time1, LocalDateTime time2) {
        long diff = Math.abs(ChronoUnit.MINUTES.between(time1, time2));
        if (diff <= DEVIATION) {
            return true;
        }
        return time1.isBefore(time2);
    }

    private boolean deviationTime1AfterTime2(LocalDateTime time1, LocalDateTime time2) {
        long diff = Math.abs(ChronoUnit.MINUTES.between(time1, time2));
        if (diff <= DEVIATION) {
            return true;
        }
        return time1.isAfter(time2);
    }
}
